﻿using LeRenard.Libraries.Templating.Templating;
using System;
using System.IO;

namespace LeRenard.Libraries.Templating
{
    /// <summary>
    /// Helper class for the <see cref="TemplateFactory"/>.
    /// </summary>
    /// <typeparam name="TTemplate">The type of <see cref="ITemplate"/> to construct.</typeparam>
    public sealed class TemplateBuilder<TTemplate>
        where TTemplate : ITemplate
    {
        /// <summary>
        /// Configures the <see cref="ITemplate"/> to load from file.
        /// </summary>
        /// <param name="fileName">The full path and file name of the template.</param>
        /// <returns>The generated <see cref="ITemplate"/>.</returns>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="fileName"/> is null or empty.</exception>
        /// <exception cref="FileNotFoundException">Thrown when file could not be found.</exception>
        public TTemplate FromFile(string fileName)
        {
            ThrowIf.NullOrEmpty(() => fileName);

            return FromFile(new FileInfo(fileName));
        }

        /// <summary>
        /// Configures the <see cref="ITemplate"/> to load from file.
        /// </summary>
        /// <param name="fileName">The full path and file name of the template.</param>
        /// <returns>The generated <see cref="ITemplate"/>.</returns>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="file"/> is null.</exception>
        /// <exception cref="FileNotFoundException">Thrown when <paramref name="file"/> could not be found.</exception>
        public TTemplate FromFile(FileInfo file)
        {
            ThrowIf.Null(() => file);
            ThrowIf.FileNotFound(() => file);

            var templateString = "";
            using (var streamReader = file.OpenText())
                templateString = streamReader.ReadToEnd();

            var template = (TTemplate)Activator
                .CreateInstance(typeof(TTemplate), new object[] { templateString });

            return template;
        }

        /// <summary>
        /// Configures the <see cref="ITemplate"/> to load from a given <paramref name="templateString"/>.
        /// </summary>
        /// <param name="templateString">The string that acts as a template.</param>
        /// <returns>The generated <see cref="ITemplate"/>.</returns>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="templateString"/> is null or empty.</exception>
        public TTemplate FromString(string templateString)
        {
            ThrowIf.NullOrEmpty(() => templateString);

            var template = (TTemplate)Activator
                .CreateInstance(typeof(TTemplate), new object[] { templateString });

            return template;
        }
    }
}
